#pragma once
#include <iostream>
#include <queue>
#include <vector>
#include <pthread.h>
#include "LockGuard.hpp"
#include "Log.hpp"
#include "Thread.hpp"
#include "Task.hpp"
#include <functional>
class ThreadData
{
public:
    ThreadData(const std::string &name) : threadname(name)
    {
    }

public:
    std::string threadname;
};

const int defaultNum = 5;
template <class T>
class ThreadPool
{
public:
    ThreadPool(int thread_num = defaultNum)
        : _thread_num(thread_num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        // 创建_thread_num个线程
        for (int i = 0; i < _thread_num; i++)
        {
            std::string threadname = "thread-";
            threadname += std::to_string(i + 1);
            ThreadData td(threadname);
            _threads.emplace_back(threadname,
                                  std::bind(&ThreadPool<T>::ThreadRun, this, std::placeholders::_1),
                                  td);
            // 打印创建线程名字的日志
            lg.LogMessage(Info, "%s is create...\n", threadname.c_str());
        }
    }

    static ThreadPool<T> *GetInstance()
    {
        if (instance == nullptr)
        {
            LockGuard lockguard(&_sig_lock);
            if (instance == nullptr)
            {
                lg.LogMessage(Info, "创建单例模式\n");
                instance = new ThreadPool<T>();
            }
        }
        return instance;
    }

    ThreadPool(const ThreadPool<T> &td) = delete;               // 不能使用拷贝构造函数
    ThreadPool<T> &operator=(const ThreadPool<T> &td) = delete; //  不能使用赋值运算符重载

    void Start()
    {
        for (auto &thread : _threads)
        {
            thread.Start();
            lg.LogMessage(Info, "%s is runing...\n", thread.GetThreadName().c_str());
        }
    }

    void ThreadRun(ThreadData &td)
    {
        while (true)
        {
            T t;
            // 取任务
            {
                LockGuard lockguard(&_mutex);
                while (_q.empty())
                {
                    ThreadWait(td);
                }
                t = _q.front();
                _q.pop();
            }

            // 处理任务
            t();
            lg.LogMessage(Debug, "%s handler task %s done, result is : %s\n",
                          td.threadname.c_str(),
                          t.PrintTask().c_str(), t.Printresult().c_str());
        }
    }

    // 在线程池中放入任务
    void Push(T &in)
    {
        lg.LogMessage(Debug, "other thread push a task, task is %s\n", in.PrintTask().c_str());
        LockGuard lockguard(&_mutex);
        _q.push(in);
        ThreadWakeup(); // 唤醒一个线程处理任务
    }

    void ThreadWakeup()
    {
        pthread_cond_signal(&_cond);
    }

    void ThreadWait(const ThreadData &td)
    {
        lg.LogMessage(Debug, "no task, %s is a sleeping...\n", td.threadname.c_str());
        pthread_cond_wait(&_cond, &_mutex);
    }
    void Wait()
    {
        for (auto &thread : _threads)
        {
            thread.Join();
        }
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

public:
    std::queue<T> _q;
    std::vector<Thread<ThreadData>> _threads;
    int _thread_num;
    pthread_mutex_t _mutex; // 锁
    pthread_cond_t _cond;   // 信号量
    static ThreadPool<T> *instance;

    static pthread_mutex_t _sig_lock; // 单例锁
};

template <class T>
ThreadPool<T> *ThreadPool<T>::instance = nullptr;

template <class T>
pthread_mutex_t ThreadPool<T>::_sig_lock = PTHREAD_MUTEX_INITIALIZER;